// ignore_for_file: file_names, must_be_immutable, constant_identifier_names, slash_for_doc_comments, avoid_unnecessary_containers, prefer_const_constructors, unnecessary_cast, sized_box_for_whitespace, prefer_function_declarations_over_variables, overridden_fields, annotate_overrides, prefer_const_literals_to_create_immutables, unnecessary_null_comparison, deprecated_member_use

import 'dart:async';
import 'package:just_audio/just_audio.dart';
import 'package:mybase/base/tool/empty/FFEmpty.dart';
import 'package:mybase/base/tool/pprint/FFLog.dart';

///音频:音乐播放器
class MusicManager {
  // 单例公开访问点
  factory MusicManager() => _sharedInstance();

  // 静态、同步、私有访问点
  static MusicManager _sharedInstance() {
    return _instance;
  }

  // 静态私有成员，没有初始化
  static final MusicManager _instance = MusicManager._();

  // 私有构造函数
  MusicManager._() {
    // 具体初始化代码
    _initPlayer();
  }

  //打印调试信息
  bool? debugPrint;

  //key为音乐ID
  Map<String, MusicStream> musicStreamMap = {};

  //播放器对象
  AudioPlayer? player;

  //当前播放ID
  String? currentPlayerId;

  //当前播放总时长
  Duration? totalDuration;

  //上一秒发送出去的进度更新
  Duration? lastSecondDuration;

  ///页面切换时 ，释放上一次的播放
  setPlayerByPageChange() async {
    await setPlayerUrl("", "___");
  }

  ///播放调用
  setPlayerUrl(String url, String playerId, {bool? debugPrint = false}) async {
    FFLog.info("准备播放 id = $playerId, url = $url");
    this.debugPrint = debugPrint;
    //TODO：释放上一次的播放状态
    await _releaseLastStatus();

    //如果是同一个playerId
    if (playerId == currentPlayerId) {
      currentPlayerId = null;
      player?.stop();
      return;
    }

    //setPlayerByPageChange
    if (FFEmpty.stringIsEmpty(url) || !url.startsWith("http")) {
      currentPlayerId = null;
      player?.stop();
      return;
    }

    currentPlayerId = playerId;
    _sendMsg(MusicStreamVO(uiState: MusicUIState.loading));

    bool loadReady = false;
    try {
      totalDuration = null;
      //不使用缓存
      //Duration? duration = await player?.setUrl(url);

      //使用缓存
      final audioSource = LockCachingAudioSource(Uri.parse(url));
      Duration? duration = await player?.setAudioSource(audioSource);

      totalDuration = duration;
      if (debugPrint == true) {
        print("总时长为 = ${totalDuration?.inSeconds}");
      }
      loadReady = true;
    } catch (e) {
      print('music player Error: An error occured: $e');
    }

    if (loadReady) {
      player?.play();
    } else {
      _sendMsg(MusicStreamVO(uiState: MusicUIState.err));
    }
  }

  //初始化
  _initPlayer() {
    player = AudioPlayer();
    player?.playbackEventStream.listen(
      (PlaybackEvent event) {},
      onError: (Object e, StackTrace st) {
        print('music player Error: listen An error occurred: $e');
        _sendMsg(MusicStreamVO(uiState: MusicUIState.err));
      },
    );

    //缓冲进度
    player?.bufferedPositionStream.listen((duration) {
      if (debugPrint == true) {
        print("bufferedPositionStream = ${duration}");
      }
    });

    //播放进度
    player?.positionStream.listen((duration) {
      if (duration.inSeconds == lastSecondDuration?.inSeconds) {
        return;
      }

      lastSecondDuration = duration;

      if (totalDuration != null) {
        _sendMsg(MusicStreamVO(
          uiState: MusicUIState.ready,
          position: duration,
          total: totalDuration,
          percent: duration.inSeconds / totalDuration!.inSeconds * 1.0,
        ));
      }
    });

    //播放状态
    player?.playerStateStream.listen((PlayerState state) {
      // idle,
      // loading,
      // buffering,
      // ready,
      // completed,
      switch (state.processingState) {
        case ProcessingState.idle:
          {
            _sendMsg(MusicStreamVO(uiState: MusicUIState.idle));
            break;
          }
        case ProcessingState.loading:
          {
            _sendMsg(MusicStreamVO(uiState: MusicUIState.loading));
            break;
          }
        case ProcessingState.buffering:
          {
            _sendMsg(MusicStreamVO(uiState: MusicUIState.buffering));
            break;
          }
        case ProcessingState.ready:
          {
            _sendMsg(MusicStreamVO(
                uiState: MusicUIState.ready,
                position: Duration.zero,
                total: totalDuration,
                percent: 0.0));
            break;
          }
        case ProcessingState.completed:
          {
            _sendMsg(MusicStreamVO(uiState: MusicUIState.completed));
            break;
          }
      }
      if (debugPrint == true) {
        print("playerStateStream = ${state.processingState}");
      }
    });
  }

  //释放上一个的UI状态
  _releaseLastStatus() async {
    totalDuration = null;
    lastSecondDuration = null;
    _sendMsg(MusicStreamVO(uiState: MusicUIState.idle));
  }

  //发送消息
  _sendMsg(MusicStreamVO vo) {
    if (FFEmpty.stringIsEmpty(currentPlayerId)) {
      if (debugPrint == true) {
        print("currentPlayerId = nil 不对/第一次");
      }
      return;
    }

    StreamController<MusicStreamVO>? streamController =
        getStreamController(currentPlayerId!);
    if (streamController == null) {
      if (debugPrint == true) {
        print("streamController == null 不对");
      }
      return;
    }

    streamController?.sink.add(vo);
  }

  setStreamController(String id, StreamController<MusicStreamVO>? controller) {
    if (musicStreamMap.containsKey(id)) {
    } else {
      musicStreamMap[id] = MusicStream(id: id, controller: controller);
    }
  }

  StreamController<MusicStreamVO>? getStreamController(String id) {
    if (musicStreamMap.containsKey(id)) {
      MusicStream? entity = musicStreamMap[id];
      if (entity != null) {
        return entity.controller;
      }
    }
    return null;
  }
}

class MusicStream {
  String id;
  StreamController<MusicStreamVO>? controller;

  MusicStream({
    required this.id,
    this.controller,
  });
}

class MusicStreamVO {
  MusicUIState uiState;
  Duration? position;
  Duration? total;
  double? percent;

  MusicStreamVO({
    required this.uiState,
    this.position,
    this.total,
    this.percent,
  });
}

enum MusicUIState {
  idle, //闲置状态
  loading, //加载中
  buffering, //缓冲中
  ready, //准备好开始播放了
  completed, //完成了
  err, //播放过程中出错了
}
